package edu.study.ops.filter;

import com.fasterxml.jackson.core.type.TypeReference;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import edu.study.api.common.constants.Constants;
import edu.study.api.common.dto.BaseRespDto;
import edu.study.api.common.dto.RespDto;
import edu.study.api.common.enums.BaseResultCodeEnum;
import edu.study.api.common.json.JsonUtils;
import edu.study.common.util.UUIDUtil;
import edu.study.common.util.cache.Cache;
import edu.study.ops.config.OpsConstant;
import edu.study.user.api.dto.UserDetailDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;

import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Component
@Slf4j
public class AddTokenPostFilter extends ZuulFilter {

    //拦截地址
    private String path = "/api/user/userApi/login";

    //拦截地址
    private List<String> paths;

    public AddTokenPostFilter() {
        super();
        paths = new ArrayList<>();
        paths.add(path);
    }

    @Autowired
    private Cache cache;

    @Autowired
    private OpsConstant opsConstant;

    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        //设置一个变量，是过滤一个登录，还是全部过滤（用作打印日志，统计性能，排查问题等）
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String uri=request.getRequestURI();
        log.debug("AddTokenPostFilter uri:{}", uri);
        PathMatcher matcher = new AntPathMatcher();
        Optional<String> optional = paths.stream().filter(t->matcher.match(t,uri)).findFirst();
        return optional.isPresent();
    }

    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        InputStream stream = context.getResponseDataStream();
        int responseStatusCode = context.getResponseStatusCode();
        context.getResponse().setContentType("application/json;charset=UTF-8");//TODO 
        if(responseStatusCode == 404) {
        	BaseRespDto result = new BaseRespDto();
            result.setResultFail(BaseResultCodeEnum.INTERFACE_NOT_FOUND);
        	context.setResponseBody(JsonUtils.toJson(result));
        	return null;
        }
        String body = null;
        try {
            body = StreamUtils.copyToString(stream, Charset.forName(Constants.UTF_8));
            if (StringUtils.isBlank(body)) {
                return null;
            }
            
            RespDto<UserDetailDto> resp = JsonUtils.fromJson(body, new TypeReference<RespDto<UserDetailDto>>(){});
            if(resp!=null && resp.getData()!=null) {
             	UserDetailDto userDetailDto = resp.getData();
                if (opsConstant.getOpsLoginOnly()) {//只允许一个登录
                    String oldToken = cache.get(userDetailDto.getUserNo());
                    if (StringUtils.isNotBlank(oldToken)) {
                        cache.del(oldToken);
                        cache.del(userDetailDto.getUserNo());
                    }
                }
                //token的逻辑可以复杂点
                String token = new StringBuffer(userDetailDto.getUserNo()).append(UUIDUtil.getRandomUuid()).toString();
                cache.put(token, JsonUtils.toJson(userDetailDto), opsConstant.getOPS_MAX_INACTIVE_INTERVAL());
                cache.put(userDetailDto.getUserNo(), token, opsConstant.getOPS_MAX_INACTIVE_INTERVAL());
                
                context.addZuulResponseHeader(Constants.TOKEN, token);//直接给前端返回一个head头
            }
            context.setResponseBody(body);
        } catch (Exception e) {
        	context.setResponseBody(body);
            log.error("AddTokenPostFilter resp={}", e);
        }
        return null;
    }
}